package com.climber.android.auth.api

import com.climber.android.commonsdk.app.AppConstants
import com.climber.android.commonres.entity.IncUserInfo
import com.climber.android.commonres.entity.UserInfo
import com.climber.android.commonsdk.api.APIError
import com.climber.android.commonsdk.api.entity.APIResponse
import com.climber.android.commonsdk.api.entity.APIResponseData
import io.ganguo.library.mvp.BaseContext
import io.ganguo.library.mvp.util.CBaseUtils
import io.reactivex.Observable
import okhttp3.RequestBody
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.POST
import java.io.Serializable

/**
 * Created by Mikes at 2020-03-17 14:48
 */
enum class LoginRegisterType : Serializable {
    Social,
    Password,                       // 手机号+密码
    SMS,                            // 手机号+验证码
    Nickname;                       // 昵称/手机号+密码
}

sealed class RegisterRequestInfo : Serializable {
    abstract fun apiParameters(): Map<String, String>

    abstract fun loginRequestInfo(): LoginRequestInfo

    // 昵称，手机号，密码
    data class Mobile(
            val nickName: String,
            val countryCode: String,
            val number: String,
            val password: String,
            val mobileOTP: String
    ) : RegisterRequestInfo() {
        override fun loginRequestInfo(): LoginRequestInfo =
                LoginRequestInfo.Mobile(countryCode + number, password)

        override fun apiParameters(): Map<String, String> = mapOf(
                Pair("nick_name", nickName),
                Pair("mobile", countryCode + number),
                Pair("password", password),
                Pair("re_password", password),
                Pair("code", mobileOTP)
        )
    }
}

sealed class LoginRequestInfo : Serializable {
    abstract fun apiParameters(): Map<String, String>

    abstract fun transferLoginType(): LoginRegisterType

    abstract fun loginMobileNumber(): String

    // 手机号 + 密码
    data class Mobile(val phoneNumber: String, val password: String) :
            LoginRequestInfo() {
        override fun transferLoginType(): LoginRegisterType = LoginRegisterType.Password

        override fun apiParameters(): Map<String, String> = mapOf(
                Pair("type", "1"),
                Pair("nick_name", phoneNumber),
                Pair("password", password)
        )

        override fun loginMobileNumber(): String = phoneNumber
    }

    // 昵称 + 密码
    data class Nickname(val nickname: String, val password: String) :
            LoginRequestInfo() {
        override fun transferLoginType(): LoginRegisterType = LoginRegisterType.Nickname

        override fun apiParameters(): Map<String, String> = mapOf(
                Pair("type", "1"),
                Pair("nick_name", nickname),
                Pair("password", password)
        )

        override fun loginMobileNumber(): String = ""
    }

    data class QQ(val user_id : String, val access_token : String, val avatar : String, val nick_name : String, val expires_in : String)
        : LoginRequestInfo(){
        override fun apiParameters(): Map<String, String> = mapOf(
                "type" to "2",
                "open_id" to user_id,
                "unionid" to "",
                "avatar" to avatar,
                "nick_name" to nick_name
        )

        override fun transferLoginType(): LoginRegisterType = LoginRegisterType.Social

        override fun loginMobileNumber(): String = ""
    }

    data class WeChat(val open_id : String, val unionid : String, val access_token : String, val avatar : String, val nick_name : String, val expires_in : String)
        : LoginRequestInfo(){
        override fun apiParameters(): Map<String, String> = mapOf(
                "type" to "3",
                "open_id" to open_id,
                "unionid" to unionid,
                "avatar" to avatar,
                "nick_name" to nick_name
        )

        override fun transferLoginType(): LoginRegisterType = LoginRegisterType.Social

        override fun loginMobileNumber(): String = ""
    }

    data class Sina(val user_id : String, val access_token : String, val avatar : String, val nick_name : String, val expires_in : String)
        : LoginRequestInfo(){
        override fun apiParameters(): Map<String, String> = mapOf(
                "type" to "4",
                "open_id" to user_id,
                "unionid" to "",
                "avatar" to avatar,
                "nick_name" to nick_name
        )

        override fun transferLoginType(): LoginRegisterType = LoginRegisterType.Social

        override fun loginMobileNumber(): String = ""
    }
}

/**
 * APP 登录，注册，找回密码等授权Service
 */
interface AuthService {
    companion object {
        val authServiceAPI: AuthService by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            CBaseUtils.obtainAppComponentFromContext(BaseContext.getInstance())
                    .repositoryManager()
                    .obtainRetrofitService(AuthService::class.java)
        }

        fun getUserCardInfoAndWalletInfo(): Observable<IncUserInfo> =
                authServiceAPI.issueGetMineUserCardInfo()
                        .flatMap {mineUserCardInfoResponse ->
                            if (mineUserCardInfoResponse.isSuccessful()) {
                                val userCardInfo = mineUserCardInfoResponse.data

                                // 登录/注册时本地无用户信息，直接新建
                                val incUserInfo = IncUserInfo()
                                incUserInfo.userInfo = userCardInfo

                                Observable.just(incUserInfo)
                            } else {
                                Observable.error(
                                        APIError.ServerError(
                                                errorCode = mineUserCardInfoResponse.getServerErrorCode(),
                                                errorMsg = mineUserCardInfoResponse.getServerErrorMsg()
                                        )
                                )
                            }
                        }
    }

    /**
     * 注册
     * body {@link RegisterRequestInfo}
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @POST("register")
    fun register(@Body apiParams: RequestBody): Observable<APIResponse>

    /**
     * 社交账号快速注册
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @POST("social/register")
    fun socialRegister(@Body apiParams: RequestBody): Observable<APIResponse>

    /**
     * 手机号码是否被注册
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @POST("verify/mobile")
    fun issueVerifyMobileIsRegistered(@Body apiParams: RequestBody): Observable<APIResponse>

    /**
     * 登录
     * body {@link LoginRequestInfo}
     *
     * type : 1,账号登录，2，QQ登录，3，微信登录，4，微博登录
     * nick_name : 用户昵称/手机号码
     * password : 密码
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @POST("login")
    fun issueGetLoginToken(@Body body: RequestBody): Observable<String>

    /**
     * 第三方登录检查是否绑定手机号
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @POST("check/bind/mobile")
    fun issueCheckBindPhoneWithSocialSignIn(@Body apiParams: RequestBody): Observable<APIResponse>

    /**
     * 忘记密码
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @POST("forget/pwd")
    fun issueForgetPassword(@Body apiParams: RequestBody): Observable<APIResponse>

    /**
     * 修改密码
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @POST("modify/pwd")
    fun issueModifyPassword(@Body apiParams: RequestBody): Observable<APIResponse>

    /**
     * 修改手机号
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @POST("modify/mobile")
    fun issueModifyPhoneNumber(@Body apiParams: RequestBody): Observable<APIResponse>

    /**
     * 用户信息
     */
    @Headers("Domain-Name: ${AppConstants.API_BASE_URL}")
    @GET("get/u/info")
    fun issueGetMineUserCardInfo(): Observable<APIResponseData<UserInfo>>
}